//
// Created by ziya on 2025/5/21.
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "token.h"
#include "buffer.h"
#include "keywords.h"

typedef enum {
    STATE_START,
    STATE_IN_NUM,
    STATE_IN_OP,
    STATE_IN_ID,
} state;

int is_digit(char c) {
    return (c >= '0' && c <= '9');
}

int is_operate(char c) {
    return c == '+' || c == '-' || c == '*' || c == '/';
}

int is_letter(char c) {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

int is_id_char(char c) {
    return is_letter(c) || is_digit(c) || c == '_';
}

token_type get_next_token(const char **content) {
    state state = STATE_START;

    char c;
    while (c = **content) {
        switch (state) {
            case STATE_START: {
                if ('\n' == c) {
                    (*content)++;
                    break;
                } else if ('_' == c) {
                    state = STATE_IN_ID;
                } else if (is_digit(c)) {
                    state = STATE_IN_NUM;
                } else if (is_operate(c)) {
                    state = STATE_IN_OP;
                } else if (is_letter(c)) {
                    state = STATE_IN_ID;
                } else {
                    // 未知字符处理
                    printf("Error: Unknown character '%c'\n", c);
                    (*content)++;

                    return TOKEN_UNKNOWN;
                }

                break;
            }
            case STATE_IN_NUM: {
                int is_float = 0;
                buffer buffer;
                buffer_init(&buffer);

                // 累积后续数字
                while (is_digit(**content) || '.' == **content) {
                    if ('.' == **content) {
                        is_float = 1;
                    }

                    buffer_append(&buffer, **content);
                    (*content)++;
                }

                printf("Number: %s(%s)\n", buffer_cstr(&buffer), is_float? "float" : "int");

                buffer_free(&buffer);

                return TOKEN_NUMBER;
            }
            case STATE_IN_OP: {
                buffer buffer;
                buffer_init(&buffer);

                buffer_append(&buffer, c);

                (*content)++;

                // +, +=, ++
                // lookahead
                if ('+' == c && ('=' == **content | '+' == **content)) {
                    buffer_append(&buffer, **content);
                    (*content)++;
                }

                printf("op: %s\n", buffer_cstr(&buffer));

                buffer_free(&buffer);

                return TOKEN_OPERATOR;
            }
            case STATE_IN_ID: {
                buffer buffer;
                buffer_init(&buffer);

                while (is_id_char(**content)) {
                    buffer_append(&buffer, **content);
                    (*content)++;
                }

                token_type type = lookup_keyword(buffer_cstr(&buffer));
                if (type == TOKEN_IDENTIFIER) {
                    printf("identifier: %s\n", buffer_cstr(&buffer));
                } else {
                    printf("keyword: %s\n", buffer_cstr(&buffer));
                }

                buffer_free(&buffer);

                return type;
            }
        }
    }

    return TOKEN_EOF;
}